Skip to content

portfwd: drain the buffer before leaving on EOF - #1228

Merged
philljj merged 2 commits into
wolfSSL:masterfrom
ejohnstown:ccb-phase2-2
Sep 4, 2026
Merged

portfwd: drain the buffer before leaving on EOF#1228
philljj merged 2 commits into
wolfSSL:masterfrom
ejohnstown:ccb-phase2-2

Conversation

@ejohnstown

@ejohnstown ejohnstown commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

A zero read on the local socket left portfwd_worker()'s loop at once and
took with it anything wolfSSH_ChannelSend() had not yet accepted, so a
transfer ending while the window is being credited came out short.

  • Stop polling the socket on end-of-input and keep looping until the
    buffer is empty.
  • Leave anyway once the channel is gone, so a forward whose open failed
    cannot hold the loop on a buffer nothing can take.
  • Push a payload several windows long through a local direct-tcpip
    forward, since scripts/fwd.test never drives past the first window.
  • End a second set of transfers a short tail past a window boundary,
    which is the shape that loses data without the drain.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new EOF handling currently treats recv() < 0 as EOF (masking socket errors), and the new shell test uses [ with -a in loop conditions in a way that is less portable/error-prone than the repo’s existing style.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes a port forwarding edge case where portfwd_worker() would exit immediately on local socket EOF, potentially dropping buffered data that had not yet been accepted by wolfSSH_ChannelSend() (e.g., while SSH window credits are in flight). It also adds a new bulk forward test to exercise transfers spanning multiple SSH windows.

Changes:

  • Update examples/portfwd/portfwd.c to stop polling the local socket on EOF and keep looping until the buffered outbound data is drained.
  • Add scripts/fwd-bulk.test to push a multi-window payload through a local direct-tcpip forward and validate byte-for-byte integrity.
  • Register the new test script in scripts/include.am so it runs under make check.
File summaries
File Description
scripts/include.am Adds the new bulk forwarding test script to the check scripts list.
scripts/fwd-bulk.test New bulk data forwarding test that verifies multi-window payload forwarding correctness.
examples/portfwd/portfwd.c Adjusts EOF handling to drain the local-to-SSH buffer before exiting the worker loop.
Review details

Suppressed comments (2)

scripts/fwd-bulk.test:172

  • Using [ with -a inside a single test expression is error-prone and less portable across /bin/sh implementations. Prefer && with separate test brackets.
while [ "$got" -lt "$payload_size" -a "$counter" -lt "$transfer_limit" ]; do

scripts/fwd-bulk.test:159

  • Using [ with -a inside a single test expression is error-prone and less portable due to historical precedence/parse quirks across /bin/sh implementations. Prefer combining two test brackets with && instead.
while [ ! -s "$fwd_ready_file" -a "$counter" -lt 20 ]; do
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread examples/portfwd/portfwd.c
Comment thread scripts/fwd-bulk.test Outdated
@ejohnstown ejohnstown self-assigned this Sep 3, 2026
A zero read on the local socket left the loop at once, and anything
read but not yet accepted by wolfSSH_ChannelSend() went with it. With
the peer's window full that tail is up to a buffer's worth, so a
transfer that ends while the window is being credited comes out short.

- stop polling the socket on end-of-input and keep looping until the
  buffer is empty
- leave anyway once the channel is gone, so a forward whose open failed
  cannot hold the loop on a buffer nothing can take
scripts/fwd.test sends eight short lines, so nothing in the suite drives
a forwarding channel past its first window, and a forward that stalled
once the window needed crediting would go unnoticed.

- push a payload several windows long through a local direct-tcpip
  forward and compare the bytes that arrive
- end a second transfer one window plus a short tail in, where the tail
  is what portfwd still holds at end-of-input, and repeat it since the
  window credit beating that tail is a race
- give the listening nc its stdin from a fifo a sleep holds open:
  reading end-of-input makes nc close the connection, which truncates
  the transfer and looks exactly like a stall
- bail out early once the byte count stops moving, so a real stall
  reports in seconds
- dump the logs on failure, check the listening nc came up, and take
  ports clear of the ones fwd.test.expect hardcodes, so a squatted or
  shared port is not reported as a stall

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1228

Scan targets checked: wolfssh-bugs, wolfssh-src

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread examples/portfwd/portfwd.c
@ejohnstown
ejohnstown requested a review from philljj September 3, 2026 22:07
@ejohnstown ejohnstown assigned wolfSSL-Bot and unassigned ejohnstown Sep 3, 2026
@philljj
philljj dismissed wolfSSL-Fenrir-bot’s stale review September 4, 2026 01:40

to be addressed in separate PR

@philljj
philljj merged commit f8b72ac into wolfSSL:master Sep 4, 2026
172 checks passed
@ejohnstown
ejohnstown deleted the ccb-phase2-2 branch September 4, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants